我們公司的專案在 rails4 所以一般我都還是在寫 controller test
一直到某天看到有 request test 才開始好奇到底跟 controller test 差別在哪?
我們先來看如果是 簡單的 Controller test 與 Request test 寫法差異
# controller test
require 'rails_helper'
RSpec.describe CollectionsController, type: :controller do
describe 'Get #index' do
it 'when resource is found' do
get :index
collection = create(:collection)
expect(response.status).to eq 200
expect(assigns(:collection)).to eq([collection])
end
end
describe 'Post #create' do
it 'redirect to index when create collection success' do
post :create, params: { collection: { title: '11', description: '222' } }
expect(response).to redirect_to(collections_path)
expect(Collection.count).to eq 1
end
end
describe 'Get #show' do
let(:collection) { create(:collection) }
it 'redirect to index when create collection success' do
get :show, params: { id: collection }
expect(response).to have_http_status(200)
expect(response).to render_template(:show)
end
end
end
# request test
require 'rails_helper'
RSpec.describe CollectionsController, type: :request do
describe 'Get #index' do
it 'when resource is found' do
get '/collections'
expect(response).to have_http_status(200)
expect(response).to render_template(:index)
end
end
describe 'Post #create' do
it 'redirect to index when create collection success' do
post '/collections', params: { collection: { title: '11', description: '222' } }
expect(response).to redirect_to(collections_path)
expect(Collection.count).to eq 1
end
end
describe 'Get #show' do
let(:collection) { create(:collection) }
it 'redirect to index when create collection success' do
get "/collections/#{collection.id}"
expect(response).to have_http_status(200)
expect(response).to render_template(:show)
end
end
end
如果遇到 host 問題 可以看這篇
其實很像只是在於 http 動詞後方路徑的寫法不同而已
在 Rails3.5 時釋放可以開始使用 Controller spec
但是到了 Rails 5 DHH 開始移除了 assigns
、assert_templete
Testing what instance variables are set by your controller is a bad idea. That's grossly overstepping the boundaries of what the test should know about. You can test what cookies are set, what HTTP code is returned, how the view looks, or what mutations happened to the DB, but testing the innards of the controller is just not a good idea.
The same goes for assert_template. This ties the test to the internal structure of how your views are organized. That's not what the test should be testing. It should be testing what DOM elements it expect to be there. Rearranging your templates and partials should not cause these tests to break. Deprecate and recommend using assert_select instead.
這邊也說到他已經移除了ActionController::TestCase
With the speed increase we achieved for ActionDispatch::IntegrationTest in Rails 5, there's no longer a need to also have ActionController::TestCase around. We're changing the scaffolds in #22076 but we should also get the message out that ActionController::TestCase is deprecated and will be made into a gem from Rails 5.1.
個人理解是鼓勵工程師將 Controller 測試改成 Request 測試
所以他才在 Rails5 的時候提升 request spec 的速度
所以你問我到底該選哪個?
==Rails3.5~4 => controller spec==
==Rails5 up => request spec==
因為在 rails5 之前 request 速度確實比 controller 還要慢
在我們自己的專案上 blog test
controller spec
request spec
但我在 rails6 自己的專案上確實 request test 速度有變快! 但其實我自己覺得速度差不多XDD 不過官方都鼓勵說要開始轉寫 request 了就照著官方的來吧!
參考來源有以下:
Deprecate assigns() and assert_template in controller testing
Deprecate ActionController::TestCase in favor of ActionDispatch::IntegrationTest
rspec relish-request spec
各個spec該如何設定host
Testing with RSpec - Request Spec
Controller Specs vs Request Specs?